package com.feng.exer2;

import com.feng.exer.CreateLinklist;
import com.feng.exer.CreateLinklistImpl;
import com.feng.exer.DefineNode;

public class OtherMethodsImpl implements OtherMethods{

    @Override
    public int AllNodes(CreateLinklistImpl linklist) {
        DefineNode temp = linklist.HeadNode;
        int sum = 0;
        if (temp.next==null){
            return 0;
        }
        while (true){
            if (temp.next==null){
                return sum;
            }
            sum++;
            temp = temp.next;
        }
    }

    @Override
    public CreateLinklistImpl CREATE_LINKLIST() {
        CreateLinklistImpl linklist = new CreateLinklistImpl();
        DefineNode node1 = new DefineNode(1001,"为什么","wsm");
        DefineNode node2 = new DefineNode(1002,"为什么呀","wsmy");
        DefineNode node3 = new DefineNode(1003,"为什么嘛","wsmm");
        linklist.add(node1);
        linklist.add(node2);
        linklist.add(node3);
        return linklist;
    }

    /**
     * 新浪面试题：
     *  找出链表中倒数第K个结点
     *  2021-07-14 18:39 --19:49
     */
    @Override
    public DefineNode Xinlang(CreateLinklistImpl linklist,int k) {
        //方法一：只遍历一次链表
            //用两个辅助链表（当然如果直接操作原来的链表的话，可以只用一个辅助链表）
        OtherMethodsImpl otherMethods = new OtherMethodsImpl();
        DefineNode temp = linklist.HeadNode.next;
        //下面这个结点当temp移动k个结点后再移动
        DefineNode temp2 = linklist.HeadNode.next;
        int i=0;
        while (temp!=null){
            if (i==k && temp.next==null){
                return temp2;
            }else if (i>k){
                temp2=temp2.next;
            }
            temp=temp.next;
            i++;
        }
        if (i<k){
            return null;
        }else {
            return temp2;
        }
    }

    @Override
    public DefineNode Xinlang2(CreateLinklistImpl linklist, int k) {
        //方法二：可以借助之前的查找链表结点个数的方法实现（只需要一个辅助链表，当然直接操作原链表的话，可以不用辅助链表）
        // 注意：直接操作原链表的头结点的前提是其不是final类型的
        OtherMethodsImpl otherMethods = new OtherMethodsImpl();
        //调用方法，查询链表的总个数nodes，用nodes-k就是当前链表所要查找的结点
        int nodes = otherMethods.AllNodes(linklist);
        //先判断总结点nodes和k值大小
        if(nodes<k){
            return null;
        }
        int n = nodes-k;
        if (n==0){
            return linklist.HeadNode.next;
        }
        DefineNode temp = linklist.HeadNode.next;
        while (n-->0){
            temp=temp.next;
        }
        //循环完，就找到了相应的结点
        return temp;
    }

    /**
     * 测试结果：
     *  报错了，不知道错误
     * 翻转前的链表：
     * DefineNode{id=1001, name='为什么', password='wsm'}
     * DefineNode{id=1002, name='为什么呀', password='wsmy'}
     * DefineNode{id=1003, name='为什么嘛', password='wsmm'}
     * DefineNode{id=1001, name='为什么', password='wsm'}
     * 翻转后的链表：
     * DefineNode{id=1001, name='为什么', password='wsm'}
     * @param linklist
     * @return
     */
    @Override
    public CreateLinklistImpl Tencent(CreateLinklistImpl linklist) {
        DefineNode temp = linklist.HeadNode.next;
        System.out.println("****"+temp.next);//为什么外面temp可以访问next值，while循环里面temp就不可以遍历了呢
        CreateLinklistImpl linklist1 = new CreateLinklistImpl();
        if (temp==null){
            return null;
        }
        while (true){
            if (temp==null){
                break;
            }
            System.out.println("if---"+temp.next.next);//if---DefineNode{id=1003, name='为什么嘛', password='wsmm'}
            //DefineNode node = temp;
            //linklist1.HeadAdd(node);

            /**
             * 这个错误是不是由于调用了外部的方法，HeadAdd(temp)把temp变量拿到外面去调
             * 用的时候改变了他的值，传回来的时候temp已经不是最开始的那个temp了
             * 如果猜测成立的话：
             *  需要使用辅助变量，定义一个结点为temp的辅助结点，作为传出去的结点，因为这个结
             *  点，只是用来存当前结点值，temp结点不能直接传出去，不然temp的下一个结点会默认
             *  被赋值为null
             * 为什么没有用呢，不是这个错误？
             *  难道这个辅助变量的传递还改变了原始变量的值？
             * 现在唯一能确定的是，调用了外部函数HeadAdd导致的错误，使temp.next为空了
             *              *  但是使用辅助变量传值没有用，也会改变temp的值，不知道为什么。
             */
            //linklist1.HeadAdd(temp);
            DefineNode tempOther = temp;
            System.out.println("temp0"+temp.next);//temp0DefineNode{id=1002, name='为什么呀', password='wsmy'}
            System.out.println("tempother0"+tempOther.next);//tempother0DefineNode{id=1002, name='为什么呀', password='wsmy'}
            linklist1.HeadAdd(tempOther);
            System.out.println("temp"+temp.next);//tempnull
            System.out.println("tempOther"+tempOther.next);//tempOthernull
            System.out.println("yyyy"+temp.next);//yyyynull
            temp = temp.next;
            System.out.println("xxxx"+temp);//xxxxnull
        }
        //linklist.HeadNode.next=linklist1.HeadNode.next;
        //return linklist;
        return linklist1;
    }
}
